package com.lifeonwalden.fincalc.utils.date;

import com.lifeonwalden.fincalc.utils.date.bean.PeriodAlignInfo;
import com.lifeonwalden.fincalc.utils.date.bean.PeriodIndex;

import java.util.Date;
import java.util.List;
import java.util.function.Function;

public interface DatePeriodUtils {
    /**
     * 获取使得两个日期序列数据日期对齐的坐标信息
     *
     * @param aDataList   升序连续的自然日序列数据
     * @param bDataList   升序的日期序列数据
     * @param aDateFetcher
     * @param <A>
     * @param <B>
     * @return
     */
    static <A,B> PeriodAlignInfo locateAlign(List<A> aDataList, List<B> bDataList, Function<A, Date> aDateFetcher, Function<B, Date> bDateFetcher) {
        int aSize = aDataList.size(), bSize = bDataList.size();
        Date aStartDate = aDateFetcher.apply(aDataList.get(0));
        Date aEndDate = aDateFetcher.apply(aDataList.get(aSize - 1));
        Date bStartDate = bDateFetcher.apply(bDataList.get(0));
        Date bEndDate = bDateFetcher.apply(bDataList.get(bSize - 1));

        PeriodAlignInfo periodAlignInfo = new PeriodAlignInfo();
        periodAlignInfo.setA(new PeriodIndex().setStartIdx(-1).setEndIndx(-1))
                .setB(new PeriodIndex().setStartIdx(-1).setEndIndx(-1));

        int startCompareResult = aStartDate.compareTo(bStartDate);
        if (startCompareResult > 0) {
            for (int i = 0; i < bSize; i++) {
                bStartDate = bDateFetcher.apply(bDataList.get(i));
                if (bStartDate.compareTo(aStartDate) >= 0) {
                    periodAlignInfo.getB().setStartIdx(i);
                    break;
                }
            }
            for (int i = 0; i < aSize; i++) {
                aStartDate = aDateFetcher.apply(aDataList.get(i));
                if (bStartDate.compareTo(aStartDate) == 0) {
                    periodAlignInfo.getA().setStartIdx(i);
                    break;
                }
            }
        } else if (startCompareResult < 0) {
            periodAlignInfo.getB().setStartIdx(0);
            for (int i = 0; i < aSize; i++) {
                aStartDate = aDateFetcher.apply(aDataList.get(i));
                if (bStartDate.compareTo(aStartDate) == 0) {
                    periodAlignInfo.getA().setStartIdx(i);
                    break;
                }
            }
        } else {
            periodAlignInfo.getA().setStartIdx(0);
            periodAlignInfo.getB().setStartIdx(0);

        }

        int endCompareResult = aEndDate.compareTo(bEndDate);
        if (endCompareResult > 0) {
            periodAlignInfo.getB().setEndIndx(bSize - 1);
            for (int i = aSize - 1; i >= 0; i--) {
                aEndDate = aDateFetcher.apply(aDataList.get(i));
                if (bEndDate.compareTo(aEndDate) == 0) {
                    periodAlignInfo.getA().setEndIndx(i);
                    break;
                }
            }
        } else if (endCompareResult < 0) {
            for (int i = bSize - 1; i >= 0; i--) {
                bEndDate = bDateFetcher.apply(bDataList.get(i));
                if (bEndDate.compareTo(aEndDate) <= 0) {
                    periodAlignInfo.getB().setEndIndx(i);
                    break;
                }
            }
            for (int i = aSize - 1; i >= 0; i--) {
                aEndDate = aDateFetcher.apply(aDataList.get(i));
                if (bEndDate.compareTo(aEndDate) == 0) {
                    periodAlignInfo.getA().setEndIndx(i);
                    break;
                }
            }
        } else {
            periodAlignInfo.getA().setEndIndx(aSize - 1);
            periodAlignInfo.getB().setEndIndx(bSize - 1);

        }

        return periodAlignInfo;
    }
}
